﻿#include "nlist.h"

void nlist_insert_first(nlist_t *nlist, nlist_node_t *node)
{
    if (!nlist || !node)
    {
        return;
    }

    if (nlist_is_empty(nlist))
    {
        nlist->first = node;
        nlist->last = node;
        node->next = NULL;
        node->pre = NULL;
    }
    else
    {
        nlist->first->pre = node;
        node->next = nlist->first;
        node->pre = NULL;
        nlist->first = node;
    }

    ++nlist->count;
}

void nlist_insert_last(nlist_t *nlist, nlist_node_t *node)
{
    if (!nlist || !node)
    {
        return;
    }

    if (nlist_is_empty(nlist))
    {
        nlist->first = node;
        nlist->last = node;
        node->next = NULL;
        node->pre = NULL;
    }
    else
    {
        nlist->last->next = node;
        node->pre = nlist->last;
        node->next = NULL;
        nlist->last = node;
    }

    ++nlist->count;
}

/**
 * @brief 在对应的节点后面插入节点
 * @param nlist 需要进行操作的链表
 * @param pre 对应的节点
 * @param node 需要被插入的节点
 */
void nlist_insert_after(nlist_t *nlist, nlist_node_t *pre, nlist_node_t *node)
{
    if (!nlist || !node)
    {
        return;
    }

    if (nlist_is_empty(nlist) || !pre)
    {
        nlist_insert_first(nlist, node);
        return;
    }

    if (pre == nlist->last)
    {
        nlist_insert_last(nlist, node);
        return;
    }

    node->next = pre->next;
    node->pre = pre;
    pre->next = node;
    node->next->pre = node;
    ++nlist->count;
}

/**
 * @brief 删除链表中对应的节点
 * @param nlist 对应链表的地址
 * @param node 要删除的节点
 */
nlist_node_t *nlist_remove(nlist_t *nlist, nlist_node_t *node)
{
    if (!nlist || !node || nlist_is_empty(nlist))
    {
        return NULL;
    }

    // 非常优雅的写法 赞！
    if (nlist->first == node)
    {
        nlist->first = node->next;
    }

    if (nlist->last == node)
    {
        nlist->last = node->pre;
    }

    if (node->pre)
    {
        node->pre->next = node->next;
    }

    if (node->next)
    {
        node->next->pre = node->pre;
    }

    --nlist->count;

    // 需不需要释放自己决定吧
    nlist_node_init(node);
    return node;
}